#include<my_header.h>

void set_type_mode(mode_t mode, char *tm_str);
void set_time(time_t mtime, char *time_str);
int compare(const void* a, const void* b);
void str_to_lower(char *str);

int main(int argc,char* argv[]){
    ARGS_CHECK(argc,2);

    DIR* drip=opendir(argv[1]);
    ERROR_CHECK(drip,NULL,"opendir");

    int ret=chdir(argv[1]);
    ERROR_CHECK(ret,-1,"chdir");

    int count=0;
    struct dirent *dp;
    
    while((dp=readdir(drip))!=NULL){
        count++;
    }

    struct dirent **dir_arr=(struct dirent**) malloc(sizeof(struct dirent*) * count);
    ERROR_CHECK(dir_arr,NULL,"malloc dlist");

    rewinddir(drip);  // 修正变量名：将dirp改为drip，保持一致性
    //lseek(dirp, 0, SEEK_SET); 错误
    //rewinddir() → 目录流（DIR*），处理缓冲。
    // lseek() → 文件描述符（int），不处理缓冲。
    
    int idx=0;
    while((dp=readdir(drip))!=NULL){
        dir_arr[idx++]=dp;
    }

    qsort(dir_arr,count,sizeof(struct dirent*),compare);

    for(int i=0;i<count;i++){
        struct stat st;
        int ret=stat(dir_arr[i]->d_name,&st);
        ERROR_CHECK(ret,-1,"stat");

        char tm_str[1024]={0};
        set_type_mode(st.st_mode,tm_str);

        char *username=getpwuid(st.st_uid)->pw_name;
        char *gname   =getgrgid(st.st_gid)->gr_name;

        char time_str[1024]={0};
        set_time(st.st_mtime,time_str);
        printf("%s %2lu %s %s %6lu %s %s\n",
            tm_str,
            st.st_nlink,
            username,
            gname,
            st.st_size,
            time_str,
            dir_arr[i]->d_name);

    }
    free(dir_arr);
    closedir(drip);  // 修正变量名：将dirp改为drip，保持一致性
    return 0;
}

void set_type_mode(mode_t mode, char *tm_str){
    // 处理第一个字符，即文件类型 
    switch (mode & S_IFMT) {
        case S_IFBLK:   tm_str[0] = 'b';        break;
        case S_IFCHR:   tm_str[0] = 'c';        break;
        case S_IFDIR:   tm_str[0] = 'd';        break;
        case S_IFIFO:   tm_str[0] = 'p';        break;
        case S_IFLNK:   tm_str[0] = 'l';        break;
        case S_IFREG:   tm_str[0] = '-';        break;
        case S_IFSOCK:  tm_str[0] = 's';        break;
        default:        tm_str[0] = '?';        break;
    }

    // 处理后续九个字符，即文件的权限信息
    // 设置拥有者的权限信息
    tm_str[1] = (mode & 0400) ? 'r' : '-';
    tm_str[2] = (mode & 0200) ? 'w' : '-';
    tm_str[3] = (mode & 0100) ? 'x' : '-';
    // 设置拥有者组的权限
    tm_str[4] = (mode & 0040) ? 'r' : '-';
    tm_str[5] = (mode & 0020) ? 'w' : '-';
    tm_str[6] = (mode & 0010) ? 'x' : '-';
    // 设置其他人的权限
    tm_str[7] = (mode & 0004) ? 'r' : '-';
    tm_str[8] = (mode & 0002) ? 'w' : '-';
    tm_str[9] = (mode & 0001) ? 'x' : '-';
    tm_str[10] = '\0'; // 确保字符串以 null 结尾
}

void set_time(time_t mtime,char *time_str){
    const char month_arr[][10]={
        "1月", "2月", "3月", "4月", "5月", "6月",
        "7月", "8月", "9月", "10月", "11月", "12月"
    };
    struct tm* st_tm=localtime(&mtime);  // 修正变量名：将time改为mtime，这才是传入的参数
    sprintf(time_str,"%s %2d %02d:%02d",
            month_arr[st_tm->tm_mon],
            st_tm->tm_mday,
            st_tm->tm_hour,
            st_tm->tm_min);  // 修正变量名：将st_tim改为st_tm，修复拼写错误

}

int compare(const void* a,const void* b){
    // 将void*类型参数a转换为struct dirent**并解引用，获取指向的dirent结构
    struct dirent* dir_a=*(struct dirent**)a;  
    // 将void*类型参数b转换为struct dirent**并解引用，获取指向的dirent结构
    struct dirent* dir_b=*(struct dirent**)b;  

    char file_name[256];
    char file_name2[256];
    strncpy(file_name,dir_a->d_name,sizeof(file_name)-1);
    strncpy(file_name2,dir_b->d_name,sizeof(file_name2)-1);  // 修正变量名：将dir_a改为dir_b，应该使用第二个目录项

    file_name[sizeof(file_name)-1]='\0';
    file_name2[sizeof(file_name2)-1]='\0';

    str_to_lower(file_name);
    str_to_lower(file_name2);

    return strcmp(file_name,file_name2);

}

void str_to_lower(char *str) {
    while (*str) {
        *str = tolower(*str);
        str++;
    }
}

